#include <glib-2.0/glib.h>
#include <time.h>

struct _audio_recorded {
    GArray *data_small;
    GArray *data;
    gsize attached_recordings;
};

typedef struct _audio_recorded audio_recorded;

static GHashTable *audio_recordings;
static GRand *random_number;


static gboolean hash_int_equal_func(gconstpointer a, gconstpointer b) {
    const int *ia = a;
    const int *ib = b;
    return *ia == *ib;
}

static  void key_destroy_func(gpointer data) {
    g_free((int *)data);
}

static void value_destroy_func(gpointer data) {
    audio_recorded *actual_data = data;
    g_free(actual_data->data);
    g_free(actual_data->data_small);
    g_free(actual_data);
}

void recording_buffer_init() {
  random_number = g_rand_new_with_seed(time(NULL));
  audio_recordings=g_hash_table_new_full(g_int_hash,g_int_equal,key_destroy_func,value_destroy_func);
}

static guint32 recording_buffer_generate_int_number() {
    return g_rand_int(random_number);
}

guint32 *recording_buffer_new_buffer() {
    guint32 *rand_key = g_new(guint32,1);
    *rand_key=recording_buffer_generate_int_number();
    audio_recorded *audio_rec = g_new(audio_recorded,1);
    
    audio_rec->data_small = g_array_new(FALSE,FALSE,sizeof(gint8));
    audio_rec->data = g_array_new(FALSE,FALSE,sizeof(double));
    audio_rec->attached_recordings=0;
    g_hash_table_insert(audio_recordings,(gpointer)&rand_key,(gpointer)audio_rec);
    g_debug("created a new audio buffer key: %d",*rand_key);
    return rand_key;
}

audio_recorded *recording_buffer_get_buffer(guint32 key) {
    g_debug("trying to get buffer key: %d",key);
    gpointer buffer = g_hash_table_lookup(audio_recordings,(gpointer)&key);
    g_assert(buffer != NULL);
    return (audio_recorded *)buffer;
} 

void recording_buffer_append_buffer_small(guint32 key, gint8 *buffer, gsize size) {
    audio_recorded *audio_buffer = recording_buffer_get_buffer(key);
    g_array_append_vals(audio_buffer->data_small,buffer,size);
}

void recording_buffer_append_buffer(guint32 key, double *buffer, gsize size) {
    audio_recorded *audio_buffer = recording_buffer_get_buffer(key);
    g_array_append_vals(audio_buffer->data,buffer,size);
}

void recording_buffer_inc_attached_recordings(guint32 key) {
    audio_recorded *buffer = recording_buffer_get_buffer(key);
    buffer->attached_recordings++;
}

void recording_buffer_dec_attached_recordings(guint32 key) {
    audio_recorded *buffer = recording_buffer_get_buffer(key);   
    g_assert(buffer->attached_recordings > 0);
    buffer->attached_recordings--;
}

GArray *recording_buffer_get_buffer_small_data(guint32 key) {
    audio_recorded *buffer = recording_buffer_get_buffer(key);   
    return buffer->data_small;
}

GArray *recording_buffer_get_buffer_data(guint32 key) {
    audio_recorded *buffer = recording_buffer_get_buffer(key);   
    return buffer->data;
}

